home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
oper_sys
/
emerald
/
emrldsys.lha
/
Language
/
Compiler
/
knowLocal.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-16
|
17KB
|
629 lines
/*
* @(#)knowLocal.c 1.8 4/11/88
*/
#include "assert.h"
#include "nodes.h"
#include "map.h"
#include "sequence.h"
#include "trace.h"
#include "semantics.h"
#include "builtins.h"
#include "primitives.h"
#include "MyParser.h"
#include "flags.h"
extern int nextLineNumber;
static Map nodeToLocalStruct;
extern Map manifestMap;
static NodePtr noneNode;
#define LC_makeGlobal(parent) LC_TryToAddDependent(parent, noneNode)
static void LC_addDependent(parent, child)
NodePtr parent, child;
{
NodePtr childStruct;
NodePtr parentStruct;
parentStruct = (NodePtr) Map_Lookup(nodeToLocalStruct, (int)parent);
if ((int)parentStruct == NIL) {
parentStruct = Construct(P_KNOWLOCAL, 3, NN, NN, NN);
parentStruct->b.knowlocal.tag = parent->tag;
parentStruct->b.knowlocal.definingThing = parent;
Map_Insert(nodeToLocalStruct, (int)parent, (int)parentStruct);
}
childStruct = (NodePtr) Map_Lookup(nodeToLocalStruct, (int)child);
if ((int)childStruct == NIL) {
childStruct = Construct(P_KNOWLOCAL, 3, NN, NN, NN);
childStruct->b.knowlocal.tag = child->tag;
childStruct->b.knowlocal.definingThing = child;
Map_Insert(nodeToLocalStruct, (int)child, (int)childStruct);
}
SET_INSERT(parentStruct->b.knowlocal.dependsOn, childStruct);
}
extern void resolveGlobal();
static void LC_TryToAddDependent(parent, child)
NodePtr parent, child;
{
Symbol st;
NodePtr at;
if (parent->tag == T_NONE) return;
if (parent->tag == P_SYMDEF || parent->tag == P_SYMREF)
parent = (NodePtr) parent->b.symref.symbol;
if (child->tag == P_SYMDEF || child->tag == P_SYMREF)
child = (NodePtr) child->b.symref.symbol;
switch (parent->tag) {
case P_SYMBOL:
st = (Symbol) parent;
at = GETVALUE(st->value.ATinfo);
if (at->b.atlit.f.immutable) return;
if (st->isManifest) {
child = noneNode;
} else if (st->itsKind == ST_Result || st->itsKind == ST_Param) {
child = noneNode;
}
break;
case P_INVOC:
if (Map_Lookup(manifestMap, (int)parent) != NIL) {
child = noneNode;
}
default:
break;
}
switch (child->tag) {
case P_SYMBOL:
st = (Symbol) child;
if (st->itsKind == ST_Result || st->itsKind == ST_Param) child = noneNode;
LC_addDependent(parent, child);
break;
case P_GLOBALREF:
resolveGlobal(child, (ValuePtr)NULL);
assert(child->b.globalref.value != NN);
LC_addDependent(parent, child->b.globalref.value);
break;
case T_NONE:
case P_INVOC:
case P_VECTORLIT:
case P_BOOLLIT:
case P_CHARLIT:
case P_INTLIT:
case P_REALLIT:
case P_STRINGLIT:
case P_BUILTINLIT:
case P_SELFLIT:
case P_ATLIT:
case P_OBLIT:
case P_NTHRESULT:
case P_EXP:
case P_UNARYEXP:
LC_addDependent(parent, child);
break;
case P_SYMREF:
assert(FALSE);
break;
default:
LC_addDependent(parent, noneNode);
break;
}
}
static Map nthMap;
static Boolean isSingleReferenceSymbol(), isACreation();
static NodePtr getNth(p, allowSelf)
NodePtr p;
Boolean allowSelf;
{
register NodePtr nth, s = p;
if (s->tag != P_INVOC && s->tag != P_SYMREF) return(s);
if (s->tag == P_INVOC && isACreation(s) && allowSelf) return(s);
if (s->tag == P_INVOC) {
#ifdef TRYINGTGETRESULTSLOCAL
This is completely garbage!
s = s->b.invoc.target;
if (s->tag != P_SYMREF || !isSingleReferenceSymbol(s)) {
nth = (NodePtr)Map_Lookup(nthMap, (int)s);
if (nth == (NodePtr)NIL) {
nextLineNumber = s->lineNumber;
nth = Construct(P_NTHRESULT, 0);
Map_Insert(nthMap, (int)s, (int)nth);
LC_makeGlobal(nth);
}
return(nth);
}
#else
nth = (NodePtr)Map_Lookup(nthMap, (int)p);
if (nth == (NodePtr)NIL) {
nextLineNumber = p->lineNumber;
nth = Construct(P_NTHRESULT, 0);
Map_Insert(nthMap, (int)p, (int)nth);
LC_makeGlobal(nth);
}
return(nth);
#endif
} else {
assert(s->tag == P_SYMREF);
nth = (NodePtr)Map_Lookup(nthMap, (int)s->b.symref.symbol);
if (nth == (NodePtr)NIL) {
nextLineNumber = s->lineNumber;
nth = Construct(P_NTHRESULT, 0);
Map_Insert(nthMap, (int)s->b.symref.symbol, (int)nth);
LC_TryToAddDependent(nth, (NodePtr)s->b.symref.symbol);
}
return(nth);
}
}
extern Map nodeToStruct;
extern NodePtr findObjectOperation(), OTLookup();
static NodePtr fetchCTInformation(p)
NodePtr p;
{
register NodePtr ct, thing;
register Symbol st;
if (p->tag == P_SYMREF || p->tag == P_SYMDEF) {
thing = (NodePtr) p->b.symdef.symbol;
} else if (p->tag == P_SYMBOL) {
thing = p;
} else {
thing = p;
}
ct = (NodePtr) Map_Lookup(nodeToStruct, (int) thing);
if (ct != (NodePtr)NIL) {
if (! ct->b.knowct.isOK) return(NULL);
ct = GETVALUE(ct->b.knowct.answer);
assert(ct != NULL);
assert(ct->tag == P_OBLIT);
} else {
ct = NN;
if (p->tag == P_SYMDEF || p->tag == P_SYMREF) {
st = p->b.symdef.symbol;
if (st->value.CTinfo != NN) ct = GETVALUE(st->value.CTinfo);
} else if (p->tag == P_SYMBOL) {
st = (Symbol) p;
if (st->value.CTinfo != NN) ct = GETVALUE(st->value.CTinfo);
}
}
return(ct);
}
static Boolean isACreation(p)
register NodePtr p;
{
NodePtr ct, opdef;
assert(p->tag == P_INVOC);
ct = fetchCTInformation(p->b.invoc.target);
if (ct == NULL) return(FALSE);
assert(ct->tag == P_OBLIT);
opdef = findObjectOperation(ct, p->b.invoc.opname);
assert(opdef != NULL);
if (! opdef->b.opdef.isInlineable) return(FALSE);
if (opdef->b.opdef.body->b.block.stats->b.children[0]->tag != P_ASSIGNSTAT) return(FALSE);
return(opdef->b.opdef.body->b.block.stats->b.children[0]->b.assignstat.right->b.children[0]->tag == P_OBLIT);
}
static Boolean isAConditionCreate(p)
register NodePtr p;
{
NodePtr ct;
assert(p->tag == P_INVOC);
ct = fetchCTInformation(p->b.invoc.target);
assert(ct != NULL);
assert(ct->tag == P_OBLIT);
return(ct->b.oblit.id == OIDOfBuiltin(B_IT, CONDITIONINDEX));
}
extern NodePtr getCTInfo();
static Boolean isSingleReferenceSymbol(s)
NodePtr s;
{
register Symbol st;
register NodePtr ct;
if (s->tag != P_SYMREF) return(FALSE);
st = s->b.symref.symbol;
if (! s->b.symref.symbol->isSingleReference) return(FALSE);
if (s->b.symref.symbol->itsKind == ST_Param) return(FALSE);
if (s->b.symref.symbol->itsKind == ST_Result) return(FALSE);
ct = getCTInfo(st);
if (ct == NULL) return(FALSE);
assert(ct->tag == P_OBLIT);
if (! ct->b.oblit.f.doesNotDuplicateSelf) return(FALSE);
if (! ct->b.oblit.f.doesNotMoveArguments) return(FALSE);
if (! ct->b.oblit.f.doesNotMoveSelf) return(FALSE);
if (! ct->b.oblit.f.resultsDependOnlyOnArgs) return(FALSE);
return(TRUE);
}
void buildKnowLocalGraph(p)
register NodePtr p;
{
register NodePtr q, right, left, nth, nthtrue;
register Symbol st;
Boolean wasACreation;
if ((int)p <= 0x200) return;
switch (p->tag) {
case P_IMPORT:
case P_EXPORT:
if (p->b.export.path == NN) break;
Sequence_For(q, p->b.export.syms)
assert(q->tag == P_SYMDEF || q->tag == P_SYMREF);
LC_makeGlobal((NodePtr) q->b.symdef.symbol);
Sequence_Next
break;
case P_ASSIGNSTAT:
right = p->b.assignstat.right;
left = p->b.assignstat.left;
if (Sequence_Length(right) > 1) {
/* is a multiple assignment */
Sequence_For(q, left)
assert(q->tag == P_SYMREF);
nth = getNth(right->b.children[z__z], TRUE);
LC_TryToAddDependent((NodePtr)q->b.symref.symbol, nth);
LC_TryToAddDependent(nth, (NodePtr)q->b.symref.symbol);
Sequence_Next
} else {
Sequence_For(q, left)
assert(q->tag == P_SYMREF);
nth = getNth(right->b.children[0], TRUE);
LC_TryToAddDependent((NodePtr)q->b.symref.symbol, nth);
LC_TryToAddDependent(nth, (NodePtr)q->b.symref.symbol);
Sequence_Next
}
break;
case P_INVOC:
if ((q = (NodePtr) Map_Lookup(manifestMap, (int)p+2)) != (NodePtr) NIL) {
/* a manifest invocation */
LC_makeGlobal(p);
break;
}
#ifdef JUNKKKKKKK
if (isACreation(p)) {
if (isAConditionCreate(p)) LC_makeGlobal(p);
} else {
LC_TryToAddDependent(p, getNth(p->b.invoc.target), TRUE);
nth = getNth(p, TRUE);
Sequence_For(q, p->b.invoc.args)
assert(q->tag == P_ARG);
q = q->b.arg.exp;
if (q->tag == P_SYMREF) {
LC_TryToAddDependent((NodePtr)q->b.symref.symbol, nth);
} else if (q->tag == P_INVOC) {
LC_TryToAddDependent(getNth(q, TRUE), nth);
} else {
LC_TryToAddDependent(q, nth);
}
LC_TryToAddDependent(nth, q);
Sequence_Next
}
#else
wasACreation = isACreation(p);
if (wasACreation && isAConditionCreate(p)) {
LC_makeGlobal(p);
} else {
if (!wasACreation) {
LC_TryToAddDependent(p, getNth(p->b.invoc.target, TRUE));
}
nth = getNth(p, FALSE);
nthtrue = getNth(p, TRUE);
Sequence_For(q, p->b.invoc.args)
assert(q->tag == P_ARG);
q = q->b.arg.exp;
if (q->tag == P_SYMREF) {
LC_TryToAddDependent((NodePtr)q->b.symref.symbol, nth);
} else if (q->tag == P_INVOC) {
LC_TryToAddDependent(getNth(q, TRUE), nth);
} else {
LC_TryToAddDependent(q, nth);
}
if (!wasACreation) {
LC_TryToAddDependent(nthtrue, q);
}
Sequence_Next
}
#endif
break;
case P_VECTORLIT:
Sequence_For(q, p->b.vectorlit.exp)
if (q->tag == P_SYMREF) {
LC_TryToAddDependent((NodePtr)q->b.symref.symbol, p);
} else if (q->tag == P_INVOC) {
LC_TryToAddDependent(getNth(q, TRUE), p);
} else {
LC_TryToAddDependent(q, p);
}
#ifdef VECTORLITERALSDEPENDONARGS
LC_TryToAddDependent(p, q);
#endif
Sequence_Next
break;
case P_CONSTDECL:
st = p->b.constdecl.sym->b.symdef.symbol;
if (st->isManifest) {
LC_makeGlobal((NodePtr)st);
break;
}
case P_VARDECL:
st = p->b.constdecl.sym->b.symdef.symbol;
if (p->b.constdecl.value != NN) {
nth = getNth(p->b.constdecl.value, TRUE);
LC_TryToAddDependent((NodePtr) st, nth);
LC_TryToAddDependent(nth, (NodePtr) st);
}
break;
case P_ATLIT:
break;
case P_OBLIT:
Sequence_For(q, p->b.oblit.setq)
if (q->b.setq.outer->tag == P_SYMREF) {
LC_makeGlobal((NodePtr)q->b.setq.outer->b.symref.symbol);
}
LC_makeGlobal((NodePtr)q->b.setq.inner->b.symdef.symbol);
Sequence_Next
LC_TryToAddDependent(p, p->b.oblit.name);
LC_TryToAddDependent(p->b.oblit.name, p);
break;
case P_VIEW:
if (p->b.view.exp->tag == P_INVOC) {
LC_makeGlobal(getNth(p->b.view.exp, TRUE));
} else {
LC_makeGlobal(p->b.view.exp);
}
break;
case P_RESTRICT:
LC_makeGlobal(p->b.restrict.exp);
break;
case P_MOVESTAT:
case P_FIXSTAT:
case P_REFIXSTAT:
LC_makeGlobal(p->b.movestat.exp);
break;
case P_UNFIXSTAT:
LC_makeGlobal(p->b.unfixstat.exp);
break;
default:
break;
}
Sequence_For(q, p)
if ((int)q > 0x200) buildKnowLocalGraph(q);
Sequence_Next
}
void initializeKnowLocal()
{
nodeToLocalStruct = Map_Create();
noneNode = Construct(T_NONE, 0);
nthMap = Map_Create();
}
static char *thingName(t)
NodePtr t;
{
static char buffer[128];
if (t->b.knowlocal.tag == P_SYMBOL) sprintf(buffer, "Symbol %s (0x%08x)",
ST_SymbolName((Symbol)(t->b.knowlocal.definingThing)), t->b.knowlocal.definingThing);
else sprintf(buffer, "%s (0x%08x) on line %d", tagNames[(int)t->b.knowlocal.tag],
t->b.knowlocal.definingThing, t->b.knowlocal.definingThing->lineNumber);
return(buffer);
}
extern void findAllLocals();
void displayKnowLocalGraph()
{
NodePtr thing, theStruct, q;
IFTRACE(knowlocal, 5) {
Map_For(nodeToLocalStruct, thing, theStruct)
printf("struct 0x%08x %s", theStruct, thingName(theStruct));
if (theStruct->b.knowlocal.isDone) {
printf(" isDone");
printf("%s", theStruct->b.knowlocal.isOK ? " isOK" : " isNotOK");
}
printf(" depends on:\n");
Set_For(q, theStruct->b.knowlocal.dependsOn)
printf("\t\tstruct 0x%08x %s\n", q, thingName(q));
Set_Next
Map_Next
}
}
#define CODEOIDOF(p) ((p)->b.oblit.codeOID)
void propagateLocalInfo(p)
NodePtr p;
{
NodePtr q, aSetMember, ct = NN, newct, dt;
Boolean isLocal = TRUE;
register Symbol st;
if (p->tag != T_SEQUENCE) p = Construct(T_SEQUENCE, 1, p);
Sequence_For(aSetMember, p)
dt = aSetMember->b.knowlocal.definingThing;
TRACE2(knowlocal, 3, "Looking at pre-reqs of 0x%08x %s", aSetMember,
thingName(aSetMember));
Set_For(q, aSetMember->b.knowlocal.dependsOn)
TRACE2(knowlocal, 4, "Looking at 0x%08x %s", q, thingName(q));
assert(q->tag == P_KNOWLOCAL);
if (! q->b.knowlocal.isDone) continue; /* it is in this set */
if (!q->b.knowlocal.isOK) {
TRACE2(knowlocal, 4, "0x%08x %s not ok, give up", q, thingName(q));
isLocal = FALSE;
}
Set_Next
if (! isLocal) break;
assert(aSetMember->tag == P_KNOWLOCAL);
if (dt->tag == P_OBLIT || dt->tag == P_SYMBOL) {
newct = fetchCTInformation(dt);
if (newct == NN) {
TRACE2(knowlocal, 4, "0x%08x %s unknown ct, give up", aSetMember,
thingName(aSetMember));
isLocal = FALSE;
} else if (ct != NN && ct != newct) {
TRACE4(knowlocal, 4, "0x%08x %s different ct (0x%x != 0x%x), give up",
aSetMember, thingName(aSetMember), CODEOIDOF(newct), CODEOIDOF(ct));
isLocal = FALSE;
} else {
ct = newct;
}
}
if (! isLocal) break;
switch (aSetMember->b.knowlocal.tag) {
case T_NONE:
isLocal = FALSE;
break;
case P_INVOC:
if (Map_Lookup(manifestMap, (int)dt + 1) != NIL) {
isLocal = FALSE;
break;
} else {
isLocal = TRUE;
}
break;
case P_NTHRESULT: /* worried about the result */
isLocal = TRUE;
break;
case P_UNARYEXP:
case P_EXP:
case P_BUILTINLIT:
case P_STRINGLIT:
case P_REALLIT:
case P_INTLIT:
case P_CHARLIT:
case P_BOOLLIT:
isLocal = FALSE;
break;
case P_VECTORLIT:
/* this could be local if its target is */
isLocal = TRUE;
break;
case P_SELFLIT:
assert(FALSE);
break;
case P_ATLIT:
isLocal = FALSE;
break;
case P_OBLIT:
isLocal = TRUE;
break;
case P_SYMBOL:
isLocal = TRUE;
break;
default:
isLocal = FALSE;
break;
}
if (!isLocal) break;
Sequence_Next
/* check that the ct is ok */
if (isLocal && ct != NN) {
if (! ct->b.oblit.f.doesNotDuplicateSelf) {
TRACE1(knowlocal, 4, "ct 0%x duplicates self, give up", CODEOIDOF(ct));
isLocal = FALSE;
}
if (! ct->b.oblit.f.doesNotMoveSelf) {
TRACE1(knowlocal, 4, "ct 0%x moves self, give up", CODEOIDOF(ct));
isLocal = FALSE;
}
}
Sequence_For(aSetMember, p)
aSetMember->b.knowlocal.isDone = TRUE;
aSetMember->b.knowlocal.isOK = isLocal;
aSetMember->b.knowlocal.answer = NULL;
TRACE3(knowlocal, 1, "Finalizing 0x%08x %s: %s", aSetMember,
thingName(aSetMember),
aSetMember->b.knowlocal.isOK ? "is local" : "is not local");
switch (aSetMember->b.knowlocal.tag) {
case P_SYMBOL:
st = (Symbol) aSetMember->b.knowlocal.definingThing;
st->isLocal = isLocal;
break;
case P_OBLIT:
aSetMember->b.knowlocal.definingThing->b.oblit.f.doLocalCreate = isLocal;
break;
case P_INVOC:
aSetMember->b.knowlocal.definingThing->b.invoc.isLocal = isLocal;
break;
case P_NTHRESULT:
break;
case P_VECTORLIT:
aSetMember->b.knowlocal.definingThing->b.vectorlit.f.doLocalCreate = isLocal;
break;
default:
break;
}
Sequence_Next
}
static int count = 0;
static NodePtr SCstack = NULL;
static NodePtr SCComponent = NULL;
#define min(A, B) ((A) < (B) ? (A) : (B))
static void localSearchC(v)
register NodePtr v;
{
register NodePtr x;
NodePtr w;
v->b.knowlocal.marked = TRUE;
v->b.knowlocal.number = count++;
v->b.knowlocal.lowLink = v->b.knowlocal.number;
Sequence_Add(&SCstack, v);
v->b.knowlocal.onStack = TRUE;
Set_For(w, v->b.knowlocal.dependsOn)
if (! w->b.knowlocal.marked) {
localSearchC(w);
v->b.knowlocal.lowLink = min(v->b.knowlocal.lowLink, w->b.knowlocal.lowLink);
} else {
if (w->b.knowlocal.number < v->b.knowlocal.number && w->b.knowlocal.onStack) {
v->b.knowlocal.lowLink = min(w->b.knowlocal.number, v->b.knowlocal.lowLink);
}
}
Set_Next
if (v->b.knowlocal.lowLink == v->b.knowlocal.number) {
TRACE0(knowlocal, 1, "------");
Sequence_ReverseFor(x, SCstack)
SCstack->nChildren --;
assert(x->b.knowlocal.onStack);
x->b.knowlocal.onStack = FALSE;
if (SCComponent == NULL && x == v) {
/* this is the only element of the component */
SCComponent = x;
} else {
Sequence_Add(&SCComponent, x);
}
TRACE2(knowlocal, 2, "struct 0x%08x %s", x, thingName(x));
if (x == v) break;
Sequence_Next
propagateLocalInfo(SCComponent);
if (SCComponent->tag == T_SEQUENCE) {
free((char *)SCComponent);
}
SCComponent = NULL;
}
}
static void FindAllLocals()
{
NodePtr theThing, theStruct;
Map_For(nodeToLocalStruct, theThing, theStruct)
if (! theStruct->b.knowlocal.marked) localSearchC(theStruct);
Map_Next
}
void doKnowLocals(p)
NodePtr p;
{
buildKnowLocalGraph(p);
displayKnowLocalGraph();
FindAllLocals();
}